package cn.acac.yygh.order.service.impl;

import cn.acac.yygh.enums.OrderStatusEnum;
import cn.acac.yygh.enums.PaymentStatusEnum;
import cn.acac.yygh.enums.PaymentTypeEnum;
import cn.acac.yygh.enums.RefundStatusEnum;
import cn.acac.yygh.exception.MyException;
import cn.acac.yygh.model.order.OrderInfo;
import cn.acac.yygh.model.order.PaymentInfo;
import cn.acac.yygh.model.order.RefundInfo;
import cn.acac.yygh.order.prop.WeixinProperties;
import cn.acac.yygh.order.service.OrderInfoService;
import cn.acac.yygh.order.service.PaymentService;
import cn.acac.yygh.order.service.RefundService;
import cn.acac.yygh.order.service.WeixinService;
import cn.acac.yygh.order.utils.HttpClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.netflix.ribbon.proxy.annotation.Http;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class WeixinServiceImpl implements WeixinService {

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private WeixinProperties weixinProperties;

    @Autowired
    private RefundService refundService;
    @Override
    public String createNative(Long orderId) {
        // 根据订单id获取订单信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        // 保存支付信息,使用微信支付
        paymentService.savePaymentInfo(orderInfo, PaymentTypeEnum.WEIXIN.getStatus());
        // 将订单信息改为支付成功
        // orderInfo.setOrderStatus(OrderStatusEnum.PAID.getStatus());
        // 将订单更新到数据库中
        // orderInfoService.updateById(orderInfo);
        // return "支付成功！";
        // 直接返回支付成功
        // 更改数据库信息
        // 请求微信服务器
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("appid",weixinProperties.getAppid());
        paramMap.put("mch_id",weixinProperties.getPartner());
        paramMap.put("nonce_str",WXPayUtil.generateNonceStr());
        Date reserveDate = orderInfo.getReserveDate();
        String reserveDateString = new DateTime(reserveDate).toString("yyyy/MM/dd");
        String body = reserveDateString + "就诊"+ orderInfo.getDepname();
        paramMap.put("body", body);
        paramMap.put("out_trade_no",orderInfo.getOutTradeNo());
        paramMap.put("total_fee", "1");//为了测试
        paramMap.put("spbill_create_ip", "127.0.0.1");
        paramMap.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify");
        paramMap.put("trade_type", "NATIVE");

        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        // 设置client参数
        try {
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(paramMap,weixinProperties.getPartnerkey()));
            httpClient.setHttps(true);      // 支持https协议
            httpClient.post(); // 发送请求
            // 获取微信服务器返回的数据
            String content = httpClient.getContent();// 返回的是xml格式的数据
            Map<String, String> stringStringMap = WXPayUtil.xmlToMap(content);
            System.out.println("stringStringMap = " + stringStringMap);
            return stringStringMap.get("code_url");

        }catch (Exception ex){
            return "";
        }
    }

    /**
     * 获取订单状态
     * @param orderId
     * @return
     */
    @Override
    public Map<String, String> getPayStatus(Long orderId) {
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        // 根据订单id查询订单信息
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        // 封装map对象
        Map<String,String> map = new HashMap<>();
        map.put("appid",weixinProperties.getAppid());
        map.put("mch_id",weixinProperties.getPartner());
        map.put("out_trade_no",orderInfo.getOutTradeNo());
        map.put("nonce_str",WXPayUtil.generateNonceStr());
        // 将map转换为xml字符串
        try {
            httpClient.setXmlParam(WXPayUtil.generateSignedXml(map,weixinProperties.getPartnerkey()));
            httpClient.setHttps(true);
            httpClient.post();
            // 返回微信服务器数据，转换为map
            return WXPayUtil.xmlToMap(httpClient.getContent());
        }catch (Exception ex){
            return null;
        }
    }

    /**
     * 查询订单支付成功后修改数据库表的方法
     * @param orderId
     * @param map
     */
    @Transactional
    @Override
    public void paySuccess(Long orderId, Map<String, String> map) {
        // 支付成功，更新订单表的数据
        OrderInfo orderInfo = orderInfoService.getById(orderId);
        orderInfo.setOrderStatus(OrderStatusEnum.PAID.getStatus()); // 将订单状态设置成已支付
        orderInfoService.updateById(orderInfo); // 更新数据
        // 更新支付表的数据
        UpdateWrapper<PaymentInfo> updateWrapper = new UpdateWrapper<>();
        // 条件
        updateWrapper.eq("order_id",orderId);
        updateWrapper.eq("out_trade_no",orderInfo.getOutTradeNo());
        // 设置参数
        updateWrapper.set("payment_status", PaymentStatusEnum.PAID.getStatus());    // 修改支付状态
        updateWrapper.set("trade_no",map.get("transaction_id"));
        updateWrapper.set("callback_time",new Date());
        updateWrapper.set("callback_content", map.toString());
        paymentService.update(updateWrapper);
    }

    /**
     * 取消预约的退款功能
     * @param orderId
     * @return
     */
    @Override
    public Boolean refund(Long orderId) {
        // 根据orderId查询出paymentInfo信息
        QueryWrapper<PaymentInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id",orderId);
        PaymentInfo paymentInfo = paymentService.getOne(queryWrapper);
        // 调用refundService将paymentInfo信息保存到退款表中
        RefundInfo refundInfo = refundService.saveRefundInfo(paymentInfo);
        // 判断退款状态是否是已退款
        if(refundInfo.getRefundStatus().equals(RefundStatusEnum.REFUND.getStatus())){
            // 已退款，直接返回
            return true;
        }
        // 请求微信服务器进行退款
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");  // 微信退款地址
        Map<String,String> refundMap = new HashMap<>(8);    // 指定容量
        refundMap.put("appid",weixinProperties.getAppid());       //公众账号ID
        refundMap.put("mch_id",weixinProperties.getPartner());   //商户编号
        refundMap.put("nonce_str",WXPayUtil.generateNonceStr());
        refundMap.put("transaction_id",paymentInfo.getTradeNo()); //微信订单号
        refundMap.put("out_trade_no",paymentInfo.getOutTradeNo()); //商户订单编号
        refundMap.put("out_refund_no","tk"+paymentInfo.getOutTradeNo()); //商户退款单号
        refundMap.put("total_fee","1");
        refundMap.put("refund_fee","1");

        // 发送请求
        try {
            String paramXml = WXPayUtil.generateSignedXml(refundMap,weixinProperties.getPartnerkey());
            httpClient.setXmlParam(paramXml);
            httpClient.setHttps(true);
            httpClient.setCert(true);
            httpClient.setCertPassword(weixinProperties.getPartner());
            httpClient.post();
            String content = httpClient.getContent();
            // 将微信服务器返回的数据转换为map
            Map<String, String> map = WXPayUtil.xmlToMap(content);
            // 判断退款是否成功
            if(map != null && "SUCCESS".equals(map.get("result_code"))){
                // 微信退款成功，将信息设置到退款表中
                refundInfo.setCallbackTime(new Date());
                refundInfo.setCallbackContent(map.toString());
                refundInfo.setTradeNo(map.get("refund_id"));
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
                refundService.updateById(refundInfo);
                return true;
            }
        }catch (Exception ex){
            ex.printStackTrace();
            System.out.println("ex.getMessage() = " + ex.getMessage());
        }
        return false;
    }
}
